<script lang="tsx" setup>
import type { FormInstance } from '@arco-design/web-vue'
import type { DnsRecordItem } from '@/apis/model/dns'
import { Message } from '@arco-design/web-vue'
import {
  addDnsAuthorityRecordApi,
  updateDnsAuthorityRecordApi,
} from '@/apis/modules/dns'
import { RECORD_TYPE_OPTIONS, RECORD_VALUE, ttlOptions } from '@/constants/dns'

interface IProp {
  record?: DnsRecordItem
}
const props = withDefaults(defineProps<IProp>(), {})
const emit = defineEmits(['reload'])
const route = useRoute()
const getTitle = computed(() => (props.record?.id ? '编辑记录' : '添加记录'))
const visible = defineModel<boolean>('visible', { required: true })
const formRef = ref<FormInstance>()
const formState = ref({
  domain: route.params.name,
  name: '',
  value: '',
  type: 'A',
  ttl: 600,
  priority: undefined,
  remark: '',
})

const recordLength = computed(() => 252 - route.params.name.length)
const rules = computed<Rules>(() => {
  const res: Rules = {
    name: [
      {
        required: true,
        validator: (value, callback) => {
          if (!value)
            return callback('主机记录不能为空')
          if (value.length > recordLength.value) {
            return callback('域名总长度不能大于 253 个字符。')
          }
        },
        message: '主机记录不能为空',
      },
    ],
    type: [{ required: true, message: '记录类型不能为空' }],
    value: [
      {
        required: true,
        validator: (value, callback) => {
          if (!value)
            return callback('记录值不能为空')
          if (formState.value.type === 'A') {
            if (!regexpMap.ipv4.test(value))
              return callback('请输入有效的 IPv4 地址，例如：192.0.2.1')
            callback()
          } else if (formState.value.type === 'AAAA') {
            if (!regexpMap.ipv6.test(value))
              return callback('请输入有效的 IPv6 地址，例如：2001:db8::1')
            callback()
          } else if (
            formState.value.type === 'CNAME'
            || formState.value.type === RECORD_VALUE.MX
          ) {
            if (!regexpMap.domain.test(value))
              return callback('请输入一个有效的域名，例如：ex.example.com')
            callback()
          } else if (formState.value.type === 'NS') {
            if (!regexpMap.domain.test(value))
              return callback('记录值格式为：域名，例如：ns1.example.com')
            callback()
          } else if (formState.value.type === 'TXT') {
            const textReg = /^[\w\s!@#$%^&*()`+\-=[\]{}|;:<>.?/,]{1,255}$/
            if (!textReg.test(value)) {
              return callback(
                `记录值不能包含中文、双引号（"）、单引号（'），长度不超过255个字符`,
              )
            }
            callback()
          } else {
            const caaRegex
              = /^(?:0|[1-9]\d?|1\d{2}|2[0-4]\d|25[0-5]) (?:issue|issuewild|iodef) (["'])(?:(?!\1).)*\1$/
            const part1
              = '记录值格式为：flag tag value，例如：0 issue "example.com"。'
            const part2
              = '每项中间以空格分隔，其中 flag 为数字，取值范围 0~255。'
            if (!caaRegex.test(value))
              return callback(`${part1}${part2}`)
            callback()
          }
        },
      },
    ],
    ttl: [{ required: true, message: 'TTL不能为空' }],
  }
  return res
})
async function handleChange() {
  formRef.value?.resetFields('value')
  await formRef.value?.validateField('value')
}

async function handleSubmit() {
  const error = await formRef.value?.validate()
  if (error)
    return false

  const fn = props.record?.id
    ? updateDnsAuthorityRecordApi
    : addDnsAuthorityRecordApi
  const data = props.record?.id
    ? { id: props.record.id!, ...formState.value }
    : {
        domain: formState.value.domain,
        record: {
          ...formState.value,
        },
      }
  await fn(data).then(() => {
    Message.success('操作成功')
  })
}
function handleOpen() {
  if (props.record?.id) {
    Object.assign(formState.value, props.record)
  }
}
function handleClose() {
  formRef.value?.resetFields()
  formState.value = {
    domain: route.params.name,
    name: '',
    value: '',
    type: 'A',
    ttl: 600,
    priority: undefined,
    remark: '',
  }
  emit('reload')
}
</script>

<template>
  <resource-dialog
    v-model:visible="visible"
    :title="getTitle"
    :width="480"
    ok-text="保存"
    :mask-closable="false"
    :before-ok="handleSubmit"
    :before-open="handleOpen"
    :before-close="handleClose"
  >
    <a-form
      ref="formRef"
      layout="vertical"
      :rules="rules"
      :model="formState"
    >
      <a-form-item
        label="主机记录"
        field="name"
        asterisk-position="end"
      >
        <a-input
          v-model="formState.name"
          :max-length="recordLength"
          class="custom-input"
          placeholder="请输入主机记录"
        >
          <template #append>
            <a-tooltip
              :content="route.params.name"
              content-class="w-50"
            >
              <div class="cursor-pointer truncate">
                .{{ route.params.name }}
              </div>
            </a-tooltip>
          </template>
        </a-input>
      </a-form-item>
      <a-form-item
        label="记录类型"
        field="type"
        asterisk-position="end"
      >
        <a-select
          v-model="formState.type"
          placeholder="请选择记录类型"
          @change="handleChange"
        >
          <template #label="{ data }">
            <section class="flex items-center gap-x-1">
              <span>{{ data?.label }}</span>
              <span class="text-[#86909C]">{{
                getOptionsLabel(RECORD_TYPE_OPTIONS, data?.value, 'desc')
              }}</span>
            </section>
          </template>
          <a-option
            v-for="region in RECORD_TYPE_OPTIONS"
            :key="region.value"
            :label="region.label"
            :value="region.value!"
          >
            <section class="flex items-center gap-x-1">
              <span>{{ region.label }}</span>
              <span class="text-[#86909C]">{{ region.desc }}</span>
            </section>
          </a-option>
        </a-select>
      </a-form-item>
      <a-form-item
        label="TTL"
        field="ttl"
        asterisk-position="end"
      >
        <a-select
          v-model="formState.ttl"
          :options="ttlOptions"
          placeholder="请选择TTL"
        />
      </a-form-item>
      <a-form-item
        label="记录值"
        field="value"
        asterisk-position="end"
      >
        <a-input
          v-model="formState.value"
          placeholder="请输入记录值"
        />
      </a-form-item>
      <a-form-item
        v-if="formState.type === RECORD_VALUE.MX"
        label="优先级"
        field="priority"
        :rules="[
          {
            required: formState.type === RECORD_VALUE.MX,
            validator(value, callback) {
              if (!value && value !== 0) {
                return callback('优先级不能为空')
              }
              else if (!/^[1-9][0-9]?$/.test(value)) {
                return callback('优先级取值范围 1-99')
              }
              callback()
            },
          },
        ]"
        asterisk-position="end"
      >
        <a-input
          v-model.number="formState.priority"
          placeholder="请输入优先级"
        />
      </a-form-item>
      <a-form-item
        label="备注"
        field="remark"
        asterisk-position="end"
      >
        <a-textarea
          v-model="formState.remark"
          :max-length="200"
          show-word-limit
          :auto-size="{ maxRows: 5, minRows: 5 }"
          placeholder="请输入备注"
        />
      </a-form-item>
    </a-form>
  </resource-dialog>
</template>

<style lang="less" scoped>
:deep(.custom-input) {
  .arco-input-append {
    max-width: 200px;
  }
}
</style>
